package com.rp.common.exception.handler;

import com.rp.common.result.ResultDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.util.WebUtils;

/**
 * 类说明:
 *
 * @author ****
 * @date 2020-12-23 14:14  新建
 */
@Slf4j
@Order(99)
@RestControllerAdvice
public class ExceptionHandler {

    @Autowired
    private Environment environment;

    /**
     * 提供对标准Spring MVC异常的处理
     *
     * @param ex      the target exception
     * @param request the current request
     */
    @org.springframework.web.bind.annotation.ExceptionHandler(Exception.class)
    public final ResponseEntity<ResultDTO<?>> exceptionHandler(Exception ex, WebRequest request) {
        // 得到异常棧的首个元素
        StackTraceElement stackTraceElement= ex.getStackTrace()[0];
        String errorMessage = "\n错误:" + ex.getMessage() + ";\n类名:" + stackTraceElement.getClassName() + ";\n文件名:" + stackTraceElement.getFileName()
                + ";\n文件行号:" + stackTraceElement.getLineNumber() + ";\n方法名:" + stackTraceElement.getMethodName();
        log.error(errorMessage);
        ex.printStackTrace();
        Profiles of = Profiles.of("dev", "test");
        ResultDTO<?> body = environment.acceptsProfiles(of) ? ResultDTO.error().message(errorMessage) : ResultDTO.error();
        HttpHeaders headers = new HttpHeaders();
        if (ex instanceof Exception) {
            return this.handleResultDTOException(ex, headers, request,body);
        }
        // TODO: 2019/10/05 galaxy 这里可以自定义其他的异常拦截
        return this.handleException(ex, headers, request,body);
    }

    /** 对ResultDTOException类返回返回结果的处理 */
    protected ResponseEntity<ResultDTO<?>> handleResultDTOException(Exception ex, HttpHeaders headers, WebRequest request, ResultDTO<?> body) {
        return this.handleExceptionInternal(ex, body, headers, HttpStatus.INTERNAL_SERVER_ERROR, request);
    }

    /** 异常类的统一处理 */
    protected ResponseEntity<ResultDTO<?>> handleException(Exception ex, HttpHeaders headers, WebRequest request, ResultDTO<?> body) {
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        return this.handleExceptionInternal(ex, body, headers, status, request);
        //
    }

    /**
     * org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler#handleExceptionInternal(java.lang.Exception, java.lang.Object, org.springframework.http.HttpHeaders, org.springframework.http.HttpStatus, org.springframework.web.context.request.WebRequest)
     * <p>
     * A single place to customize the response body of all exception types.
     * <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
     * request attribute and creates a {@link ResponseEntity} from the given
     * body, headers, and status.
     */
    protected ResponseEntity<ResultDTO<?>> handleExceptionInternal(
            Exception ex, ResultDTO<?> body, HttpHeaders headers, HttpStatus status, WebRequest request) {

        if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
            request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
        }
        return new ResponseEntity<>(body, headers, status);
    }
}
